package ca.uoit.dblp;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import ca.uoit.dblp.AuthorGraph.EdgeFunc;
import ca.uoit.dblp.AuthorGraph.Entry;
import ca.uoit.dblp.AuthorGraph.NeighbourhoodFunc;

public class Algorithm {
	public static void walk(AuthorGraph G, EdgeFunc alter) {
		for(long i1: G.E.keySet()) {
			Map<Long, Entry> neighbours = G.E.get(i1);
			for(long i2: neighbours.keySet()) {
				Entry e = neighbours.get(i2);
				alter.call(i1, i2, e);
			}
		}
	}
	
	public static void walk(AuthorGraph G, NeighbourhoodFunc alter) {
		for(long i1: G.E.keySet()) {
			Map<Long, Entry> neighbours = G.E.get(i1);
			alter.call(i1, neighbours);
		}
	}
	
	public static class D0 implements EdgeFunc {
		public void call(long i, long j, Entry e) {
			e.d0 = Math.exp(-0.1 * e.count);
		}
	}
	
	public static class Transitive implements NeighbourhoodFunc {
		private AuthorGraph G;
		private Set<Long> currentNeighbours;
		public Transitive(AuthorGraph G) {
			this.G = G;
			this.currentNeighbours = new HashSet<Long>();
		}
		public void call(long i, Map<Long, Entry> N) {
			this.currentNeighbours.clear();
			this.currentNeighbours.addAll(N.keySet());

			for(long j: currentNeighbours) {
				Map<Long, Entry> theirNeighbourhood = this.G.E.get(j);
				if(theirNeighbourhood == null)
					continue;
				
				Entry e_ij = N.get(j);
				assert(e_ij != null);
				Set<Long> theirNeighbours = theirNeighbourhood.keySet();
				theirNeighbours.removeAll(currentNeighbours);
				for(long k: theirNeighbours) {
					Entry e_jk = theirNeighbourhood.get(k);
					// TODO: we do not guarantee shortest path recorded in Entry of (i,k)
					if(e_jk.count > 0 && (! N.containsKey(k))) {
						double d0 = e_ij.d0 + e_jk.d0;
						Entry e_ik = new Entry(0, d0);
						assert(e_ik != null);
						N.put(k, e_ik);
					}
				}
			}
		}
	}
}
